//
//  Protocol.swift
//  swiftDemo
//
//  Created by yaqiang bi on 2017/3/30.
//  Copyright © 2017年 毕小强. All rights reserved.
//
//  协议

import UIKit

class ProtocolVC: UIViewController,DiceGameDelegate{
    func gameDidEnd(_ game: DiceGame) {
        
    }

    func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
        print("游戏正在进行中:\(diceRoll)")
    }

    func gameDidStart(_ game: DiceGame) {
        
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white
        
        struct Personal:FullyNamed,AnotherProtocol {
            var fullName:String
            static var someTypeProperty:Int = 0
        }
        
        let json = Personal(fullName:"Json")
        print(json.fullName)
        print(Personal.someTypeProperty)
        
        class 星际飞船:FullyNamed{
            var prefix:String?
            var name:String
            init(name:String,prefix:String? = nil) {
                self.name = name
                self.prefix = prefix
            }
            var fullName:String{
                return (prefix != nil ? prefix! + " ":"") + name
            }
        }
        let ncc1701 = 星际飞船(name:"麒麟号",prefix:"宇宙级")
        print(ncc1701.fullName)
        

        let generator = 随机算法()
        print(generator.random())
        print(generator.random())
        
        enum OnOffSwitch:Togglable{
            case ON,OFF
            mutating func toggle(){
                switch self {
                case .ON:
                    self = .OFF
                case .OFF:
                    self = .ON
                }
            }
        }
        
        
        class 一个基类{
            init() {
                
            }
        }
        
        class 一个子类:一个基类,构造协议{
            override required init(){
                //因为重写父类方法,所以使用override
                //因为遵守协议,所以使用required
            }
        }
        

        
        let d6 = Dice(sides:6,generator:随机算法())
        for _ in 1...5{
            print("Random dice roll is \(d6.roll())")
        }
        
        //委托代理模式
        let snake = SnakesAndLaddres()
        snake.delegate = self
        snake.play()
        
        
        //通过扩展添加协议一致性
        print(d6.textualDescription)
        print(snake.textualDescription)
        
        //协议类型的集合
        let hamster = Hamster(name: "Jack")
        let things:[TextRepresentable] = [snake,hamster,d6]
        for thing in things {
            print(thing.textualDescription)
        }
        
        print(snake.prettyTextualDescription)
        
        //协议合成
        let birthdayStudent = Student(name: "小明", age: 12)
        wishHappyBirthday(to: birthdayStudent)
        
        //检查协议一致性
        let objects:[AnyObject] = [
            Circle(radius: 2.0),
            Square(area: 20000),
            Animal(legs: 4)
        ]
        for object in objects {
            if let objectWithArea = object as? HasArea {
                print(objectWithArea.area)
            }else{
                print("Nothing")
            }
        }
        
        //可选协议
        let counter = Counter()
        counter.count = -4
        counter.dataSource = ThreeSource()
        for _ in 0..<5 {
            counter.inscream()
            print("可选协议:\(counter.count)")
        }
        
        //协议扩展
        print("Here's a random number:\(generator.random())")
        print("And here's a random Boolean: \(generator.randomBool())")
        
        //给协议扩展添加限制
        let murray1 = Hamster(name: "Murray")
        let murray2 = Hamster(name: "Morgan")
        let murray3 = Hamster(name: "Maurice")
        let hamsters = [murray1,murray2,murray3]
        print(hamsters.textualDescription)
        // Do any additional setup after loading the view.
    }
    
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */

}

protocol FullyNamed {
    var fullName:String{get}
}
protocol AnotherProtocol {
    static var someTypeProperty:Int{get set}
}

protocol Togglable {
    mutating func toggle()
}
protocol 构造协议 {
    init ()
}

protocol SomeProtocol {
    var mustBeSettalble:Int {get set}
    var doesNotNeedToBeSettable: Int { get }
    static func someTypeMethod()
}

protocol RandomNumberGenerator {
    func random() -> Double
}
class Dice {
    let sides:Int
    let generator:RandomNumberGenerator
    init(sides:Int,generator:RandomNumberGenerator) {
        self.sides = sides
        self.generator = generator
    }
    
    func roll() ->Int {
        return Int(generator.random()*Double(sides))+1
    }
}

protocol DiceGame {
    var dice:Dice{get}
    func play()
}
protocol DiceGameDelegate {
    func gameDidStart (_ game:DiceGame)
    func game(_ game:DiceGame,didStartNewTurnWithDiceRoll diceRoll:Int)
    func gameDidEnd(_ game:DiceGame)
}
class SnakesAndLaddres: DiceGame {
    let finalSquare = 25
    let dice = Dice(sides:6,generator:随机算法())
    var square = 0
    var board:[Int]
    init() {
        board = [Int](repeating:0,count:finalSquare+1)
        board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
        board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
    }
    var delegate:DiceGameDelegate?
    func play()  {
        square = 0
        delegate?.gameDidStart(self)
        gameLoop:while square != finalSquare{
            let diceRoll = dice.roll()
            delegate?.game(self,didStartNewTurnWithDiceRoll:diceRoll)
            switch square + diceRoll {
            case finalSquare:
                break gameLoop
            case let newSquare where newSquare > finalSquare:
                continue gameLoop
            default:
                square += diceRoll
                square += board[square]
            }
        }
        delegate?.gameDidEnd(self)
    }
}

class 随机算法:RandomNumberGenerator{
    var lastRandom = 42.0
    let m = 139968.0
    let a = 3877.0
    let c = 29573.0
    func random() -> Double {
        lastRandom = lastRandom * a + c
        lastRandom = lastRandom.truncatingRemainder(dividingBy:m)
        return lastRandom / m
    }
}

//通过扩展添加协议一致性
protocol TextRepresentable{
    var textualDescription:String{get}
}
extension Dice:TextRepresentable{
    var textualDescription:String
    {
        return "A \(sides)-sided dice"
    }
}
extension SnakesAndLaddres:TextRepresentable{
    var textualDescription:String{
        return "A game of Snakes and Ladders with \(finalSquare) squares"
    }
}



//通过扩展遵循协议
/*
 *      当一个类型已经符合了某个协议中的所有要求，却还没有声明遵循该协议时，可以通过空扩展体的扩展来遵循该协议
 **/
struct Hamster{
    var name:String
    
    var textualDescription:String
    {
        return "A hamster named \(name)"
    }
}
extension Hamster:TextRepresentable{}


//协议的继承
protocol PrettyTextRepresentable:TextRepresentable{
    var prettyTextualDescription: String { get }
}
extension SnakesAndLaddres:PrettyTextRepresentable{
    var prettyTextualDescription:String{
        var output = textualDescription + ":\n"
        for index in 1...finalSquare {
            switch board[index] {
            case let ladder where ladder > 0:
                output += "▲"
            case let snake where snake < 0:
                output += "▼"
            default:
                output += "○"
            }
        }
        return output
    }
}

//类类型专属协议 
/*
 *      声明在最左侧的class标识,只能被类遵守的协议
 **/
protocol SomeClassOnlyProtocol:class{

}
class onlyClass: SomeClassOnlyProtocol {
    
}

//协议合成 &
protocol Named{
    var name:String{get}
}
protocol Aged {
    var age:Int{get}
}
struct Student:Named,Aged {
    var name:String
    var age:Int
}
func wishHappyBirthday(to celebrator:Named&Aged){
    print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}

//检查协议一致性 is as
protocol HasArea{
    var area:Double{get}
}
class Circle: HasArea {
    let pi = 3.1415926
    var radius:Double
    var area: Double{return pi*radius*radius}
    init(radius:Double) {
        self.radius = radius
    }
}
class Square: HasArea {
    var area: Double
    init(area:Double) {
        self.area = area
    }
}
class Animal {
    var legs:Int
    init(legs:Int) {
        self.legs = legs
    }
}

///可选协议
@objc protocol CounterDataSource{
    @objc optional func incrementForCount(count:Int) -> Int
    @objc optional var fixedIncrement:Int{get}
}
class Counter {
    var count = 0
    var dataSource:CounterDataSource?
    func inscream()  {
        if let amount = dataSource?.incrementForCount?(count: count) {
            count += amount
        }else if let amount = dataSource?.fixedIncrement{
            count += amount
        }
    }
}
class ThreeSource:NSObject,CounterDataSource{
    let fixedIncrement: Int = 3
    func incrementForCount(count: Int) -> Int {
        if count == 0 {
            return 0
        }else if count < 0 {
            return 1
        }else{
            return -1
        }
    }
}

///协议扩展 提供默认实现
extension RandomNumberGenerator{
    func randomBool() ->Bool {
        return random() > 0.5
    }
}

extension Collection where Iterator.Element:TextRepresentable{
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joined(separator: ", ") + "]"
    }
}





